const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')

const { spawn } = require('child_process')
const path = require('path')
const electron = require('electron')

const { parseArgs, info, error, makeConfig, compileCallback, DEFAULT_TARGETS } = require('./util')
const args = parseArgs(process.argv.slice(2), {
  boolean: [ 'debug' ]
})

// 可接受参数
const env = process.env.NODE_ENV || 'production'
const port = '9080'
const debug = args[ 'debug' ] || false

function startRenderer () {
  return new Promise((resolve, reject) => {
    const config = makeConfig(DEFAULT_TARGETS.renderer, env, require('./config/webpack.base.vue.config'), {
      plugins: [
        new webpack.HotModuleReplacementPlugin()
      ]
    })
    const options = {
      contentBase: false,
      hot: true,
      host: 'localhost',
      quiet: true,
      before (app, ctx) {
        ctx.middleware.waitUntilValid(() => {
          resolve()
        })
      }
    }
    WebpackDevServer.addDevServerEntrypoints(config, options)
    const compiler = webpack(config)
    compiler.hooks.done.tap('done', stats => {
      info(stats.toString({
        chunks: false,
        colors: true
      }) + '\n', 'render')
    })
    const server = new WebpackDevServer(compiler, options)
    server.listen(+port)
  })
}

function startMain () {
  return new Promise((resolve, reject) => {
    const config = makeConfig(DEFAULT_TARGETS.main, env)
    const compiler = webpack(config)
    compiler.hooks.done.tap('done', stats => {
      info(stats.toString({
        chunks: false,
        colors: true
      }) + '\n', 'main')
    })
    compiler.watch({
      aggregateTimeout: 300,
      poll: undefined
    }, compileCallback(resolve, reject))
  }).then(out => { }).catch(err => {
    error('\n' + err + '\n', 'main')
    throw new Error()
  })
}

let electronProcess = null

function startElectron () {
  let startArgs = []
  if (debug) {
    startArgs.push('--inspect-brk')
  }
  startArgs.push(path.join(__dirname, '../dist/main.js'))

  electronProcess = spawn(electron, startArgs)
  electronProcess.stdout.on('data', data => {
    info(data.toString(), 'electron')
  })
  electronProcess.stderr.on('data', data => {
    error(data.toString(), 'electron')
  })

  electronProcess.on('close', () => {
    info('electron closed. process will close too.', 'electron')
    process.exit()
  })
}

function start () {
  Promise.all([ startMain(), startRenderer() ]).then(() => {
    startElectron()
  }).catch(e => {
    error(e)
  })
}

start()
